#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
主题: 序列化Python对象
问题: 你需要将一个Python对象序列化为一个字节流，以便将它保存到一个文件、存储到数据库或者通过网络传输它。
提示 :
"""

import pickle
import time
import threading

filename = '21_serialize_object.bin'

print(f"{filename = }")

def recipe1():
    data = Data('car')

    # 输出到文件
    f = open(filename, 'wb')
    pickle.dump(data, f)
    f.close()

def recipe2():
    '''字节流中恢复一个对象'''
    f = open(filename, 'rb')
    print(f"{pickle.load(f) = }")

def recipe3():
    data = Data('car')
    s = pickle.dumps(data)
    print(f"{s = }")
    print(f"{pickle.loads(s) = }")

def recipe4():
    f = open(filename, 'wb')
    pickle.dump([1, 2, 3, 4], f)
    pickle.dump('hello', f)
    pickle.dump({'Apple', 'Pear', 'Banana'}, f)
    f.close()

    f = open(filename, 'rb')
    print(f"{pickle.load(f) = }")
    print(f"{pickle.load(f) = }")
    print(f"{pickle.load(f) = }")

def recipe5():
    '''序列化函数，类，还有接口'''
    import math
    print(f"{pickle.dumps(math.cos) = }")

def recipe6():
    c = Countdown(10)
    time.sleep(3)

    f = open(filename, 'wb')
    pickle.dump(c, f)
    f.close()

    f = open(filename, 'rb')
    pickle.load(f)

    time.sleep(10)

class Data:
    def __init__(self, name) -> None:
        self.name = name

    def __repr__(self) -> str:
        return 'Data({!r})'.format(self.name) 

class Countdown:
    def __init__(self, n) -> None:
        self.n = n
        self.thr = threading.Thread(target=self.run)
        self.thr.daemon = True
        self.thr.start()
    
    def run(self):
        while self.n > 0:
            print('T-minus', self.n)
            self.n -=1
            time.sleep(1)
    
    def __getstate__(self):
        return self.n

    def __setstate__(self, n):
        self.__init__(n)

def main():
    print('recipe1'.center(20, '*'))
    recipe1()
    print('recipe2'.center(20, '*'))
    recipe2()
    print('recipe3'.center(20, '*'))
    recipe3()
    print('recipe4'.center(20, '*'))
    recipe4()
    print('recipe5'.center(20, '*'))
    recipe5()
    print('recipe6'.center(20, '*'))
    recipe6()

if __name__ == '__main__':
    main()           